#include "bdfaceengine.h"

#include <QNetworkRequest>
#include <QNetworkReply>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>//搜索人脸时会用到，不能丢，否则提示“has initializer but incomplete type”
#include <QDebug>
#include <QEventLoop>
#include <QBuffer>
#include <QPixmap>

#include <QFile>
#include <QTextStream>

#include <QMessageBox>
#include "config.h"


BdFaceEngine::BdFaceEngine(QObject *parent) : QObject(parent)
{
    m_apiKey = API_KEY;
    m_secretKey = SECRET_KEY;
    m_dThresholdValue = REC_THRESHOLD;

    qDebug() << m_http.supportedSchemes();
    refresh_token();
}


bool BdFaceEngine::refresh_token()
{
    //1.构建QNetworkRequest
    QNetworkRequest request(QUrl(QString(OATH_PATH)));//api接口
    QByteArray Append = QString("grant_type=client_credentials&client_id=%1&client_secret=%2").arg(m_apiKey).arg(m_secretKey).toUtf8();
    request.setRawHeader("Content-Type", "Application/json");

    //2. 发送http请求
    //const auto &&flag = m_http.post(request, Append, buf, 15000);//超时为15000ms, 此处的m_http应该是JasonQt_Face的类成员
    QNetworkReply *reply = m_http.post(request,Append);

    //3. 阻塞接收http回复
    QEventLoop eventLoop;
    QObject::connect(reply, SIGNAL(finished()),&eventLoop, SLOT(quit()));
    eventLoop.exec(QEventLoop::ExcludeUserInputEvents);
    if(reply->error() != QNetworkReply::NoError)
    {
        //return reply->error();
        return false;
    }
    QByteArray responseData = reply->readAll();
    //qDebug() << responseData;
#if 0
    if(!flag) { return false; }

    const auto &&data = QJsonDocument::fromJson(buf).object();
    if(data.isEmpty() || !data.contains("access_token")) { return false; }

    //测试得到：(每次都不一样)
    //24.13f5ae2a35bc2b8972309dd3e0d08378.2592000.1717305108.282335-65414810
    //"access_token": "24.0757dae0d4762f74127959a5773e3033.2592000.1717299220.282335-65414810"
    //24.25c2535ab70a9ff2a02ca553b08898e9.2592000.1717306563.282335-65414810
    m_token = data["access_token"].toString();
    return true;
#endif
    //4. 解析返回的Json结果
    QJsonParseError json_error;
    QJsonDocument jsonDoc(QJsonDocument::fromJson(responseData, &json_error));

    reply->deleteLater();
    if(json_error.error != QJsonParseError::NoError)
    {
        return false;
    }
    QJsonObject rootObj = jsonDoc.object();
    if(rootObj.isEmpty() ||(!rootObj.contains("access_token"))){ return false;}
    m_token = rootObj.value("access_token").toString();
    qDebug() << m_token;
    return true;
}

/*
 * @func:在数据库中注册人脸，返回其user_id
 * @desc:需要指定分组、图片的base64编码
*/
int BdFaceEngine::register_face_core(const QString &qstrImage, const QString & user_info, int user_id)
{
    //1. 设置请求相关内容
    QUrl url(REGISET_PATH+m_token);
    QNetworkRequest request(url);

    request.setRawHeader("Content-Type", "application/json");

    /*
     * {
            "group_id": "2",
            "image": "/9j/4AAQSkZJRgABAQEASABIAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw...已省略部分数据，点击复制按钮获取全部...FB//2Q==",
            "image_type": "BASE64",
            "user_id": "3",
            "user_info": "姚晨"
        }
    */

#if 0 //使用字符串方式，是不可以的
    QByteArray Append = QString(REGISTER_JSON_MODEL)
            .arg(group_id)
            .arg(qstrImage)
            .arg("BASE64")
            .arg(user_id)
            .arg(user_info).toUtf8();

    //qDebug() << Append;
#else
    QJsonObject Append;
    Append["group_id"] = GROUP_ID;
    Append["image"] = qstrImage;//face dat
    Append["image_type"]="BASE64";
    Append["user_id"] = user_id;
    Append["user_info"] = user_info;

    QJsonDocument document;
    document.setObject(Append);
    QByteArray AppendByteArray = document.toJson(QJsonDocument::Compact);
    //QString strJson(byteArray);

    //调试
    //qDebug() << AppendByteArray;
#endif

    QNetworkReply *reply = m_http.post(request,AppendByteArray);
    //3. 阻塞接收http回复
    QEventLoop eventLoop;
    QObject::connect(reply, SIGNAL(finished()),&eventLoop, SLOT(quit()));
    eventLoop.exec(QEventLoop::ExcludeUserInputEvents);
    if(reply->error() != QNetworkReply::NoError)
    {
        //return reply->error();
        qDebug() << "reply error";
        return -1;
    }
    QByteArray responseData = reply->readAll();
    qDebug() << responseData;
/*
 * {
    "error_code": 0,
    "error_msg": "SUCCESS",
    "log_id": 559117337,
    "timestamp": 1714716559,
    "cached": 0,
    "result": {
        "face_token": "a6e7a740186a9e42f0a7a619a7a534f0",
        "location": {
            "left": 184.84,
            "top": 186.96,
            "width": 288,
            "height": 279,
            "rotation": 0
        }
    }
    }
*/

    //4. 解析发送来的json数据
    QJsonObject rootObj(QJsonDocument::fromJson(responseData).object());

    int debug_err_code = 0;
    //检查是否注册成功
    if(responseData.isEmpty())
    {
        debug_err_code = 1;
        goto failed;
    }
    if(rootObj.isEmpty())
    {
        debug_err_code = 2;
        goto failed;
    }
    if(!rootObj.contains("result"))
    {
        debug_err_code = 3;
        goto failed;
    }


    {
        int err_code = rootObj.value("error_code").toInt();
        qDebug() << "ErrorCode:" << err_code;
        if(err_code!=0)
        {
            qDebug() << rootObj.value("error_msg").toString();
            return -1;
        }
        else
        {
            return user_id;
        }
    }
    //else
    {
    failed:
        qDebug() << "Primary check failed, debug_err_code="<<debug_err_code;
        qDebug() << rootObj.value("error_msg").toString();
        return -1;
    }
}


/*
 * @func:在数据库中搜索人脸，返回其user_id
 * @desc:需要指定分组、图片的base64编码
*/
int BdFaceEngine::search_face_core(QString &qstrImage)
{
    //1. 设置请求相关内容
    QUrl url(SEARCH_PATH+m_token);
    QNetworkRequest request(url);

    request.setRawHeader("Content-Type", "aspplication/json");

/*
 * {
    "group_id_list": "2",
    "image": "iVBORw0KGgoAAAANSUhEUgAAAoAAAAHgCAIAAAC6s0uzAAAACXBIWXMAABYlAAAWJQ...已省略部分数据，点击复制按钮获取全部...rkJggg==",
    "image_type": "BASE64"
    }
*/
    QJsonObject Append;
    Append["image"] = qstrImage;//face dat
    Append["image_type"]="BASE64";
    Append["group_id_list"] = GROUP_ID;
    //Append["quality_control"]="NORMAL";

    QJsonDocument document;
    document.setObject(Append);
    QByteArray AppendByteArray = document.toJson(QJsonDocument::Compact);

    //2. 发送请求
    //m_http.post(request, QJsonDocument(Append).toJson(), buf, 15000);
    QNetworkReply *reply = m_http.post(request,AppendByteArray);

    //3. 阻塞接收http回复
    QEventLoop eventLoop;
    QObject::connect(reply, SIGNAL(finished()),&eventLoop, SLOT(quit()));
    eventLoop.exec(QEventLoop::ExcludeUserInputEvents);
    if(reply->error() != QNetworkReply::NoError)
    {
        //return reply->error();
        return false;
    }
    QByteArray responseData = reply->readAll();
/*
 * {
    "error_code": 0,
    "error_msg": "SUCCESS",
    "log_id": 299582808,
    "timestamp": 1714716299,
    "cached": 0,
    "result": {
        "face_token": "73532efea111d803615c5ec7e40625af",
        "user_list": [
            {
                "group_id": "2",
                "user_id": "1",
                "user_info": "赵文昱",
                "score": 95.989372253418
            }
        ]
    }
*/
    //4. 解析发送来的json数据
    QJsonObject rootObj(QJsonDocument::fromJson(responseData).object());
    //检查合法性
    if(responseData.isEmpty() || rootObj.isEmpty() /*|| !rootObj.contains("result")*/)
    {
        return -1;
    }
    //数据解析
    QJsonObject result=rootObj.value("result").toObject();

    if(result.contains("user_list"))
    {
        QJsonArray user_list =  result.value("user_list").toArray();
        QJsonObject userObj = user_list.at(0).toObject();

        double score = userObj["score"].toDouble();
        QString user_id=userObj["user_id"].toString();

        qDebug()<<"user_id:" << user_id;
        qDebug()<<"user_info:" <<userObj["user_info"].toString();
        qDebug()<<"可信度:" << score;
        int tmp=user_id.toInt();
        if(score>=m_dThresholdValue)
            return tmp;
        else
            return -1;
    }
return -1;
}

int BdFaceEngine::register_face(const QString &imgpath, const QString &user_info, int user_id)
{
    //尝试注册
    QString imgstr =  build_imgstr(imgpath);

    int ret = register_face_core(imgstr, user_info,user_id);
    if(ret >0)
    {
        qDebug() <<"注册成功";
        //QMessageBox::information(this, "注册提示","注册成功");
    }
    else
    {
        qDebug() <<"注册失败";
       // QMessageBox::information(this, "注册提示","注册失败");
    }
    emit register_done(ret);
    return ret;
}

int BdFaceEngine::search_face(const QString &imgpath)
{
    QString imgstr =  build_imgstr(imgpath);
    int ret = search_face_core(imgstr);
    if(ret > 0)
    {
        qDebug() <<"查询成功";
        //QMessageBox::information(this, "查询提示","查询成功");
    }
    else
    {
        qDebug() <<"查询失败";
        //QMessageBox::information(this, "查询提示","查询失败");
    }
    emit search_done(ret);
    return ret;
}



QString BdFaceEngine::build_imgstr(const QString &imgpath)
{
    QPixmap image(imgpath); //我希望输入的参数是QPixmap
    if(image.isNull())
    {
        qDebug() <<  "image is NULL";
        return "";
    }
    QByteArray bytearray;
    QBuffer buffer(&bytearray);
    buffer.open(QIODevice::WriteOnly);
    image.save(&buffer,"jpg");
    QByteArray img64 = bytearray.toBase64();//base64编码

    QFile file("output.txt");
    if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
    {
        qDebug()<<"file open failed";
    }
    else
    {
        QTextStream m_out(&file);
        m_out << img64;
    }

    return img64;
}

QString BdFaceEngine::build_imgstr(QPixmap &image)
{
    //QPixmap image("Lena.JPG"); //我希望输入的参数是QPixmap
    QByteArray bytearray;
    QBuffer buffer(&bytearray);
    buffer.open(QIODevice::WriteOnly);
    image.save(&buffer,"jpg");
    QByteArray img64 = bytearray.toBase64();//base64编码

    return img64;
}

QString BdFaceEngine::build_imgstr(QByteArray &bytearray)
{
    QByteArray img64 = bytearray.toBase64();//base64编码
    return img64;
}









